#include"MyRpcChannel.h"
#include"RpcHeader.pb.h"
#include"zookeeperutil.h"
#include<sys/types.h>
#include<sys/socket.h>
#include<RpcApplication.h>
#include<string>
#include<unistd.h>
#include<arpa/inet.h>

void MyRpcChannel::CallMethod(const google::protobuf::MethodDescriptor* method,
                          google::protobuf::RpcController* controller, const google::protobuf::Message* request,
                          google::protobuf::Message* response, google::protobuf::Closure* done)
{
  const google::protobuf::ServiceDescriptor * service = method->service();
  std::string serviceName = service->name();
  std::string methodName = method->name();

  uint32_t argSize =0;
  std::string argBuff;
  if(request->SerializeToString(&argBuff))
  {
    argSize = argBuff.size();
  }else
  {
    std::cout<<"serialize request erro"<<std::endl;
    controller->SetFailed("serialize request erro");
    return ;
  }
  
   rpc::RPC_HEADER rpcHeader;
   rpcHeader.set_servicename(serviceName);
   rpcHeader.set_methodname(methodName);
   rpcHeader.set_argsize(argSize);

   uint32_t headSize =0;
   std::string rpcHeaderBuff;
   if(rpcHeader.SerializeToString(&rpcHeaderBuff))
   {
      headSize = rpcHeaderBuff.size();
   }else
   {
     std::cout<<"serialize rpcHeader erro"<<std::endl;
     controller->SetFailed("serialize rpcHeader erro");
     return ;
   }
   std::string sendBuff;
   sendBuff.insert(0,std::string((char*)&headSize,4));
   sendBuff += rpcHeaderBuff;
   sendBuff += argBuff;
     std::cout<<"headSize :"<<headSize<<std::endl;
     std::cout<<"rpcHeaderBuff:"<<rpcHeaderBuff<<std::endl;
     std::cout<<" serviceName:"<< serviceName<<std::endl;
     std::cout<<"methodName:"<<methodName<<std::endl;
     std::cout<<"argSize:"<<argSize<<std::endl;
   int fd = socket(AF_INET,SOCK_STREAM,0);
   if(-1 == fd)
   {
    std::cout<<"socket error"<<std::endl;
     controller->SetFailed("socket error");
     close(fd);
     return ;
   }
   /*
   ZKClient zkcli;
   zkcli.Start();
   std::string methodPath = "/" + serviceName +"/"+methodName;
   std::string hostData = zkcli.GetData(methodPath.c_str());
   if(hostData == "")
   {
      controller->SetFailed(methodPath+"is not exist!");
      return ;
   }
   int idx = hostData.find(":");
   if(idx == -1)
   {
      controller->SetFailed(methodPath+"address is invalid!");
      return ;
   }
   std::string ip = hostData.substr(0,idx);
   uint16_t port = atoi(hostData.substr(idx+1,hostData.size()-idx).c_str());
   */
   std::string ip {"127.0.0.1"};
   uint16_t port = 8000;
   struct sockaddr_in serverAddr;
   serverAddr.sin_family = AF_INET;
   serverAddr.sin_port = htons(port);
   serverAddr.sin_addr.s_addr = inet_addr(ip.c_str());

   if(-1 == connect(fd,(struct sockaddr *)(&serverAddr),sizeof(serverAddr)))
   {
    std::cout<<"connect error"<<std::endl;
    controller->SetFailed("connect error");
    close(fd);
    exit(-1);
   }
  if(-1 == send(fd,sendBuff.c_str(),sendBuff.size(),0))
  {
     std::cout<<"send error"<<std::endl;
     controller->SetFailed("send error");
     close(fd);
     exit(-1);
  }
  char recvBuf[1024];
  uint32_t recvSize =0;
 if(-1 ==(recvSize = recv(fd,recvBuf,1024,0)))
  {
    std::cout<<"recv error"<<std::endl;
    controller->SetFailed("recv error");
    close(fd);
    exit(-1);
  }
  if(!response->ParseFromArray(recvBuf,recvSize))
  {
    std::cout<<"parse erro"<<std::endl;
    controller->SetFailed("parse erro");
    close(fd);
    exit(-1);
  }
  close(fd);

}